package com.yanqu.road.server.gameplayer.module.manor;

import com.alibaba.fastjson.JSON;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.config.fishpond.FishPondBadgeConfig;
import com.yanqu.road.entity.config.fishpond.FishPondEventInfo;
import com.yanqu.road.entity.config.fishpond.FishPondItemConfig;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.config.skill.SkillUpgradeInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.*;
import com.yanqu.road.entity.manor.*;
import com.yanqu.road.entity.player.PatronsFishBindingData;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.logic.bussiness.player.UserFishPondBusiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.helper.CalcPowerResult;
import com.yanqu.road.logic.helper.PowerHelper;
import com.yanqu.road.pb.manor.FishPondProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.rankunionwar.RankUnionWarModule;
import com.yanqu.road.server.gameplayer.module.manor.fishPondTaskCondition.BaseFishPondCondition;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.BadgeModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.EarnSpeedModule;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.activity.strongholdwar.StrongholdActivityMgr;
import com.yanqu.road.server.manger.activity.unionwar.UnionPhaseWarMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SkillMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.maidian.manor.ManorFishLog;
import com.yanqu.road.server.manger.manor.FishPondMgr;
import com.yanqu.road.server.manger.manor.ManorMgr;
import com.yanqu.road.server.manger.rank.RankMgr;
import com.yanqu.road.server.pb.FishPondPb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.LocalDateTimeHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ：zfr
 * @date ：2021/10/11 15:17
 */
public class ManorFishPondModel {
    private Map<Integer, FishData> fishDataMap; //fishId 鱼类数据
    private Map<Integer, FishPondSpecialItemData> fishPondSpecialItemDataMap;   //itemId 奇物数据
    private FishPondData fishPondData;  //鱼塘数据
    private Map<Long, BaseFishPondCondition> taskConditionMap;  //委托任务
    private GamePlayer player;
    private Map<Integer, PatronsFishBindingData> patronsFishBindingDataMap;
    private List<FishPondProto.FishCurrencyTemp.Builder> fishCurrencyAddSyncList = new ArrayList<>(); //需要同步的获得鱼的数据
    private static Logger logger = LogManager.getLogger(ManorFishPondModel.class.getName());
    private boolean isHundredFishing = false;
    private boolean isRedWorm = false;
    private List<Integer> hundredFishingFinishTaskList = new ArrayList<>();
    private Property hundredFishingFinishTaskReward = new Property();


    public ManorFishPondModel(FishPondData fishPondData, Map<Integer, FishData> fishDataMap,
                              Map<Integer, FishPondSpecialItemData> fishPondSpecialItemDataMap,
                              List<FishPondTaskData> fishPondTaskDataList, Map<Integer, PatronsFishBindingData> bindingDataMap,
                              GamePlayer player) {
        this.fishPondData = fishPondData;
        if (this.fishPondData == null) {
            this.fishPondData = new FishPondData(player.getUserId());
            this.fishPondData.setInsertOption();
        }
        this.fishDataMap = fishDataMap;
        this.fishPondSpecialItemDataMap = fishPondSpecialItemDataMap;
        this.patronsFishBindingDataMap = bindingDataMap;
        this.player = player;
        taskConditionMap = new ConcurrentHashMap<>();
        for (FishPondTaskData taskData : fishPondTaskDataList) {
            BaseFishPondCondition baseFishPondCondition = BaseFishPondCondition.createCondition(player, taskData);
            if (baseFishPondCondition != null) {
                if (!taskData.isGetReward()) {
                    baseFishPondCondition.addToPlayer();
                }
                taskConditionMap.put(baseFishPondCondition.getFishPondTaskData().getId(), baseFishPondCondition);
            }
        }
    }

    Map<Integer, PatronsFishBindingData> getPatronsFishBindingDataMap() {
        return patronsFishBindingDataMap;
    }

    public Map<Integer, FishData> getFishDataMap() {
        return fishDataMap;
    }

    public Map<Integer, FishPondSpecialItemData> getFishPondSpecialItemDataMap() {
        return fishPondSpecialItemDataMap;
    }

    public boolean isHundredFishing() {
        return isHundredFishing;
    }
    public boolean isRedWorm() {
        return isRedWorm;
    }

    public List<Integer> getHundredFishingFinishTaskList() {
        return hundredFishingFinishTaskList;
    }

    public Property getHundredFishingFinishTaskReward() {
        return hundredFishingFinishTaskReward;
    }

    /**
     * 初始化鱼塘数据
     */
    public void init() {
        if (this.fishPondData == null) {
            this.fishPondData = new FishPondData(player.getUserId());
            this.fishPondData.setInsertOption();
        }
        //初始化体力恢复时间(初始可以领多少体力 走配置) 初始化鱼塘徽章等级
        fishPondData.init(FishPondMgr.initRecoveryTime(), FishPondMgr.getInitBadgeLv());
        syncFishPondData();
        player.getModule(EarnSpeedModule.class).scheduleAddSilver();
        // 初始化鱼塘勋章
        updateBadge();
    }

    public FishPondData getFishPondData() {
        return fishPondData;
    }

    /**
     * 重置钓珍稀鱼判定状态
     */
    void resetFishingState() {
        clearJudge(true);
        clearJudgeSync(true);
    }

    /**
     * 同步客户端鱼塘数据
     */
    void syncFishPondData() {
        FishPondProto.FishPondDataMsg.Builder syncData = FishPondPb.parseFishPondData(fishPondData, fishDataMap, fishPondSpecialItemDataMap, taskConditionMap);
        player.sendPacket(ClientProtocol.U_FISH_POND_DATA_SYNC, syncData);
    }

    /**
     * 同步客户端鱼类数据
     */
    private void syncFishData(List<FishData> fishDataList) {
        FishPondProto.SyncFishDataMsg.Builder syncData = FishPondProto.SyncFishDataMsg.newBuilder();
        for (FishData fishData : fishDataList) {
            syncData.addFishData(FishPondPb.parseFishData(fishData));
        }
        player.sendPacket(ClientProtocol.U_FISH_POND_SYNC_FISH_DATA, syncData);
    }

    /**
     * 同步客户端奇物数据
     */
    private void syncSpecialItem(List<FishPondSpecialItemData> specialItemDataList) {
        FishPondProto.SyncSpecialItemMsg.Builder syncData = FishPondProto.SyncSpecialItemMsg.newBuilder();
        for (FishPondSpecialItemData specialItemData : specialItemDataList) {
            syncData.addSpcialItem(FishPondPb.parseSpecialItemData(specialItemData));
        }
        player.sendPacket(ClientProtocol.U_FISH_POND_SYNC_SPECIAL_ITEM, syncData);
    }

    /**
     * 同步客户端委托任务数据
     */
    private void syncTaskData() {
        FishPondProto.SyncTaskDataMsg.Builder syncData = FishPondProto.SyncTaskDataMsg.newBuilder();
        for (BaseFishPondCondition condition : taskConditionMap.values()) {
            if (!condition.isGetReward()) {
                FishPondTaskData taskData = condition.getFishPondTaskData();
                syncData.addTask(FishPondPb.parseFishPondTaskData(taskData));
            }
        }
        player.sendPacket(ClientProtocol.U_FISH_POND_SYNC_TASK_DATA, syncData);
    }

    private void syncSingleFish(FishData fishData) {
        syncFishData(Collections.singletonList(fishData));
    }

    public void syncSingleSpecialItem(FishPondSpecialItemData specialItemData) {
        syncSpecialItem(Collections.singletonList(specialItemData));
    }

    /**
     * 处于珍稀鱼判定过程
     * @return bool
     */
    private boolean isFishingJudging() {
        if (fishPondData.getFishingState() == 1) {
            //判定超时时间
            if (System.currentTimeMillis() - fishPondData.getFishingJudgeTime()
                    < FishPondMgr.FISHING_JUDGING_OVER_TIME_SECOND * DateHelper.SECOND_MILLIONS) {
                return true;
            } else {
                clearJudge(false);
                AutoLogMgr.add(new LogFishPondFishing(player.getUserId(), 0, 0, 0, fishPondData.getJudgeFishId()));
                logger.error("fishing judge time is over, judge fail, fishId:{}", fishPondData.getJudgeFishId());
                return false;
            }
        }
        return false;
    }

    /**
     * 体力恢复
     */
    public void getEnergy(FishPondProto.GetFishPondEnergyRespMsg.Builder respMsg) {
        long recoveryTime = fishPondData.getRecoveryTime();
        String[] split = GameConfig.FISHPOND_ENERGY_RECOVERY_PARAM.split(",");
        CalcPowerResult calcPowerResult = PowerHelper.calcPower(recoveryTime / 1000,
                Integer.parseInt(split[1]) * DateHelper.MINUTE_SECONDS, Integer.parseInt(split[0]), Integer.parseInt(split[2]), 0);
        int recoveryCount = calcPowerResult.getCurPower();
        Property reward = new Property();
        if (recoveryCount > 0) {
            reward.addProperty(GameConfig.FISHPOND_FISHING_ITEM_ID, BigInteger.valueOf(recoveryCount));
            player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.Manor, eLogMoneyType.ManorFishPondGetEnergy);
            fishPondData.setRecoveryTime(calcPowerResult.getLastRecoverTime() * 1000);
        }
        respMsg.setRet(0);
        respMsg.setReward(PropertyHelper.parsePropertyToString(reward));
        respMsg.setRecoveryTime(calcPowerResult.getLastRecoverTime() * 1000);
    }


    /**
     * 钓鱼
     *
     * @param times 次数
     * @return ret 结果
     */
    public int fishing(int times,int baitId) {
        try {
            //是否解锁
            if (!FishPondMgr.checkFishPondOpen(player)) {
                return GameErrorCode.E_FISH_POND_IS_LOCK;
            }
            //次数 单次或者10次或百次
            if (times != 1 && times != 10 && times != 100) {
                return GameErrorCode.E_FISH_POND_FISHING_TIMES_ERROR;
            }
            boolean needJudge = true;
            //是否允许十连
            if (times == 10) {
                //vip解锁
                if (calcRarityFishAccCount() < GameConfig.FISHPOND_TEN_FISHING_VIP_RARITY_QUALITY_NUM_LIMIT) {
                    return GameErrorCode.E_FISH_POND_TEN_FISHING_CONDITION_NO_COMPLETE;
                }
                needJudge = false;
            }
            if (times == 100) {
                if (fishPondData.getFishPondLv() < GameConfig.FISHPOND_HUNDRED_FISHING_BADGE_LIMIT) {
                    return GameErrorCode.E_FISH_POND_BADGE_LV_NOT_ENOUGH;
                }
                needJudge = false;
            }
            //是否处于珍稀鱼判定过程
            if (isFishingJudging()) {
                return GameErrorCode.E_FISH_POND_FISHING;
            }
            int fishingConsumeNum = FishPondMgr.getFishingConsumeNum(times);
            //体力是否足够
            Property consume;
            if(baitId == GameConfig.FISHPOND_FISHING_ITEM_ID){
                consume = new Property(GameConfig.FISHPOND_FISHING_ITEM_ID, BigInteger.valueOf(fishingConsumeNum));
            }else if(baitId == GameConfig.FISHPOND_FISHING_RED_WORM_ITEM_ID){
                consume = new Property(GameConfig.FISHPOND_FISHING_RED_WORM_ITEM_ID, BigInteger.valueOf(fishingConsumeNum));
            }else{
                return GameErrorCode.E_FISH_POND_ENERGY_NO_ENOUGH;
            }
            if (!player.getModule(CurrencyModule.class).removeCurrency(consume, eLogMoneyType.Manor, eLogMoneyType.ManorFishPondFishingCost)) {
                return GameErrorCode.E_FISH_POND_ENERGY_NO_ENOUGH;
            }
            if (times == 100) {
                isHundredFishing = true;
                isRedWorm = false;
                if(baitId == GameConfig.FISHPOND_FISHING_RED_WORM_ITEM_ID){
                    isRedWorm = true;
                }
                // 自动完成委托任务先领奖
                if(baitId != GameConfig.FISHPOND_FISHING_RED_WORM_ITEM_ID){
                    if (fishPondData.isAutoFinishTask()) {
                        taskConditionMap.keySet().forEach(this::getTaskReward);
                    }
                }
            }
            FishPondProto.FishingRespMsg.Builder respMsg = FishPondProto.FishingRespMsg.newBuilder();
            respMsg.setRet(0);
            List<FishingResult> fishingResultList = new ArrayList<>();
            for (int i = 0; i < times; i++) {
                player.notifyListener(eFishPondEventType.FishingTimes.getIntValue(), 1);
                fishingResultList.add(randomFishingResult(needJudge,baitId));
            }
            for (FishingResult result : fishingResultList) {
                respMsg.addResult(FishPondPb.parseFishingResult(result));
            }
            if (isHundredFishing) {
                respMsg.addAllFinishTask(hundredFishingFinishTaskList);
                respMsg.setTaskReward(PropertyHelper.parsePropertyToString(hundredFishingFinishTaskReward));
            }
            syncFishPondData();
            player.notifyListener(eGamePlayerEventType.FishingTimes.getValue(), times);
            player.sendPacket(ClientProtocol.U_FISH_POND_FISHING, respMsg);

            //钓鱼埋点
            ManorFishLog.trackNewFishPond(player, fishingResultList);
        } catch (Exception e) {
            logger.error(e);
        } finally {
            isRedWorm = false;
            isHundredFishing = false;
            hundredFishingFinishTaskList.clear();
            hundredFishingFinishTaskReward = new Property();
        }
        return 0;
    }

    /**
     * 随机钓鱼结果
     * @param needJudge 需要判定
     * @return FishingResult 钓鱼结果
     */
    private FishingResult randomFishingResult(boolean needJudge,int baitId) {
        FishingResult fishingResult = new FishingResult();
        int dayNight = FishPondMgr.getDayNight();
        //随机事件类型 委托任务已满 移除委托任务事件
        int weather = ManorMgr.getManorWeatherList().get(0).getWeather();
        FishPondEventInfo fishPondWeight = FishPondMgr.randomFishingEvent(taskConditionMap, fishPondSpecialItemDataMap, weather, dayNight, fishDataMap);
        fishingResult.setEventType(fishPondWeight.getType());
        fishingResult.setEventId(fishPondWeight.getEventId());
        boolean isJudging = false;
        //根据类型随机具体事件
        if (fishPondWeight.getType() == eFishingEventType.Fish.getValue()) {
            int boxId = Integer.parseInt(fishPondWeight.getReward());
            FishPondItemConfig fishPondItemConfig = FishPondMgr.randomFish(boxId, weather, dayNight, fishDataMap, false,baitId);
            //随机重量
            int randomFishWeight = FishPondMgr.randomFishWeight(fishPondItemConfig);
            isJudging = addFish(fishPondItemConfig, randomFishWeight, needJudge);
            fishingResult.setId(fishPondItemConfig.getId());
            fishingResult.setWeight(randomFishWeight);
            if(!isJudging) {
                notifyFishingFishTask(fishPondItemConfig);
            }

            //钓鱼埋点
            //ManorFishLog.trackFishPond(player, fishPondItemConfig);
        } else if (fishPondWeight.getType() == eFishingEventType.SpecialItem.getValue()) {

            int itemId = Integer.parseInt(fishPondWeight.getReward().split("=")[0]);
            GoodsInfo goodsInfo = GoodsMgr.getGoodsById(itemId);
            addSpecialItem(goodsInfo, Long.valueOf(fishPondWeight.getReward().split("=")[1]));
            fishingResult.setId(goodsInfo.getGoodsId());
            notifyFishingSpecialItemTask(fishPondSpecialItemDataMap.get(goodsInfo.getGoodsId()));

        } else if (fishPondWeight.getType() == eFishingEventType.Task.getValue()) {
            String extendParam = fishPondWeight.getExtendParam();
            String[] param = extendParam.split("\\|");
            int taskId = Integer.parseInt(param[0]);
            int npcId = FishPondMgr.randomTaskNpcId(param[1]);
            int textIndex = FishPondMgr.randomTaskTextIndex(Integer.parseInt(param[3]));
            String fishType = addTask(taskId, npcId, textIndex, fishPondWeight.getEventId());
            fishingResult.setId(taskId);
            fishingResult.setNpcId(npcId);
            fishingResult.setTextIndex(textIndex);
            fishingResult.setExtendParam(fishType);
        }

        //日志
        AutoLogMgr.add(new LogFishPondFishing(player.getUserId(), weather, fishPondWeight.getEventId(), isJudging ? 2 : 1, fishingResult.getId()));
        return fishingResult;
    }

    /**
     * 触发钓鱼任务事件
     * @param config 鱼类配置
     */
    private void notifyFishingFishTask(FishPondItemConfig config) {
        player.notifyListener(eFishPondEventType.FishingFishCount.getIntValue(), 1);
        player.notifyListener(eFishPondEventType.FishingTypeFishCount.getIntValue(), config.getId());
        player.notifyListener(eFishPondEventType.FishingQualityFishCount.getIntValue(), config.getQuality());
    }

    /**
     * 触发奇物任务事件
     * @param specialItemData 奇物数据
     */
    public void notifyFishingSpecialItemTask(FishPondSpecialItemData specialItemData) {
        player.notifyListener(eFishPondEventType.FishingTypeSpecialItemCount.getIntValue(), specialItemData);
    }

    /**
     * 新增鱼
     * @param config 鱼类配置
     * @param randomFishWeight 随机的重量
     * @param needJudge 珍稀鱼需要进行判定
     * */
    public boolean addFish(FishPondItemConfig config, long randomFishWeight, boolean needJudge) {
        //珍稀鱼
        if (FishPondMgr.isRarityFish(config) && needJudge) {
            //置为珍稀鱼判定状态 1
            fishPondData.setFishingState(1);
            //判定时间为当前
            fishPondData.setFishingJudgeTime(System.currentTimeMillis());
            fishPondData.setJudgeFishId(config.getId());
            fishPondData.setJudgeFishWeight(randomFishWeight);
            return true;
        }
        if (!fishDataMap.containsKey(config.getId())) {
            FishData fishData = new FishData(player.getUserId());
            //鱼类初始化
            int num = 0;
            if (config.getQuality() < GameConfig.FISHPOND_EQUIP_FISH_QUALITY_LIMIT) {
                num = 1;
            }
            fishData.init(config, randomFishWeight, num, 1);
            notifyFishSkillUnLock(fishData);
            fishDataMap.put(fishData.getFishId(), fishData);
        } else {
            FishData data = fishDataMap.get(config.getId());
            data.setNum(data.getNum() + 1);
            data.setAccFishingCount(data.getAccFishingCount() + 1);
            data.setRealFishingCount(data.getRealFishingCount() + 1);
            //重量新高
            if (data.getHighestWeight() < randomFishWeight) {
                data.setHighestWeight(randomFishWeight);
            }
        }
        //加钓鱼积分
        addFishPondScore(config.getFisherPoints());

        //日志
        AutoLogMgr.add(new LogFishPondItem(player.getUserId(), config.getId(), true, 1,
                fishDataMap.get(config.getId()).getNum(), config.getFisherPoints(), eLogMoneyType.ManorFishPondFishingGet.getValue()));
        return false;
    }

    /**
     * 后台发道具
     * @param goodsId 道具id
     * @param count 数量
     * @param son
     */
    public void addFishCurrency(int goodsId, long count, eLogMoneyType son) {
        try {
            FishPondItemConfig config = FishPondMgr.getFishPondItemConfig(goodsId);
            if (config == null) {
                return;
            }

            for (int i = 0; i < count; i++) {
                int randomFishWeight = FishPondMgr.randomFishWeight(config);
                boolean isInit = false;
                if (!fishDataMap.containsKey(config.getId())) {
                    isInit = true;
                    FishData fishData = new FishData(player.getUserId());
                    int initNum = 0;
                    if (config.getQuality() < GameConfig.FISHPOND_EQUIP_FISH_QUALITY_LIMIT) {
                        initNum = 1;
                    }
                    fishData.init(config, randomFishWeight, initNum, 0);
                    notifyFishSkillUnLock(fishData);
                    fishDataMap.put(fishData.getFishId(), fishData);
                } else {
                    FishData data = fishDataMap.get(config.getId());
                    data.setNum(data.getNum() + 1);
                    data.setAccFishingCount(data.getAccFishingCount() + 1);
                    //重量新高
                    if (data.getHighestWeight() < randomFishWeight) {
                        data.setHighestWeight(randomFishWeight);
                    }
                }
                //加钓鱼积分
                addFishPondScore(config.getFisherPoints());

                //同步给客户端弹窗显示
                FishPondProto.FishCurrencyTemp.Builder fishTemp = FishPondProto.FishCurrencyTemp.newBuilder();
                fishTemp.setFishId(config.getId());
                fishTemp.setWeight(randomFishWeight);
                fishTemp.setIsNew(isInit);
                fishCurrencyAddSyncList.add(fishTemp);
            }
            syncSingleFish(fishDataMap.get(goodsId));
            syncFishPondData();

            //日志
            AutoLogMgr.add(new LogFishPondItem(player.getUserId(), config.getId(), true, count,
                    fishDataMap.get(goodsId).getNum(), 0, son.getValue()));
        } catch (Exception e) {
            logger.error("addFishCurrency error , goodId:{}, count:{}", goodsId, count, e);
        }
    }

    /**
     * 新增奇物
     * @param goodsInfo 物品配置
     */
    private void addSpecialItem(GoodsInfo goodsInfo, long count) {
        if (!fishPondSpecialItemDataMap.containsKey(goodsInfo.getGoodsId())) {
            FishPondSpecialItemData specialItemData = new FishPondSpecialItemData(player.getUserId());
            //奇物初始化
            specialItemData.init(goodsInfo);
            fishPondSpecialItemDataMap.put(specialItemData.getSpecialItemId(), specialItemData);
        }
        FishPondSpecialItemData specialItemData = fishPondSpecialItemDataMap.get(goodsInfo.getGoodsId());
        specialItemData.setCount(specialItemData.getCount() + count);
        long addScore = Long.parseLong(goodsInfo.getExtendParam().split("\\|")[0]) * count;
        addFishPondScore(addScore);

        //日志
        AutoLogMgr.add(new LogFishPondItem(player.getUserId(), goodsInfo.getGoodsId(), true, count,
                specialItemData.getCount(), addScore, eLogMoneyType.ManorFishPondFishingGet.getValue()));
    }

    /**
     * 捕获稀有鱼
     * @param success 成功与否
     */
    public int catchRarityFish(boolean success) {
        //不处于捕获珍稀鱼状态
        if (fishPondData.getFishingState() != 1) {
            return GameErrorCode.E_FISH_POND_NOT_FISHING_STATE;
        }
        FishPondProto.RarityFishJudgeRespMsg.Builder respMsg = FishPondProto.RarityFishJudgeRespMsg.newBuilder();
        respMsg.setRet(0);
        try {
            FishPondItemConfig fishPondItemConfig = FishPondMgr.getFishPondItemConfig(fishPondData.getJudgeFishId());

            if (success) {
                //加鱼
                addFish(fishPondItemConfig, fishPondData.getJudgeFishWeight(), false);
                notifyFishingFishTask(fishPondItemConfig);
                respMsg.setFishId(fishPondItemConfig.getId());
                syncFishPondData();
                AutoLogMgr.add(new LogFishPondFishing(player.getUserId(), 0, 0, 1, fishPondItemConfig.getId()));
            } else {
                AutoLogMgr.add(new LogFishPondFishing(player.getUserId(), 0, 0, 0, fishPondItemConfig.getId()));
            }

            player.sendPacket(ClientProtocol.U_FISH_POND_RARITY_FISH_JUDGE, respMsg);
        } catch (Exception e) {
            logger.error("catch rarity fish error", e);
        } finally {
            clearJudge(false);
            clearJudgeSync(false);
        }
        return 0;
    }

    /**
     * 清除判定状态
     * @param isLogin
     */
    private void clearJudge(boolean isLogin) {
        if (fishPondData.getFishingState() == 1) {
            int fishId = fishPondData.getJudgeFishId();
            fishPondData.setFishingState(0);
            fishPondData.setJudgeFishId(0);
            fishPondData.setJudgeFishWeight(0);
            if (isLogin) {
                AutoLogMgr.add(new LogFishPondFishing(player.getUserId(), 0, 0, 0, fishId));
                logger.info("login clear fishing judge state, judge fishId:{}", fishId);
            }
        }
    }

    private void clearJudgeSync(boolean isLogin) {
        FishPondProto.FishingStateClearSyncMsg.Builder syncMsg = FishPondProto.FishingStateClearSyncMsg.newBuilder();
        syncMsg.setType(isLogin ? 2 : 1);
        player.sendPacket(ClientProtocol.U_FISH_POND_FISHING_STATE_CLEAR, syncMsg);
    }

    /**
     * 接受委托任务
     * @param taskId 任务id
     * @param npcId npcId
     * @param textIndex textIndex
     * @param eventId 事件id
     */
    public String addTask(int taskId, int npcId, int textIndex, int eventId) {
        String extendParam = "";
        if (taskConditionMap.size() < GameConfig.FISHPOND_TASK_NUM_LIMIT) {
            FishPondTaskData taskData = new FishPondTaskData();
            taskData.setUserId(player.getUserId());
            taskData.setId(taskConditionMap.size() + 1);
            taskData.setInsertOption();
            extendParam = createTaskCondition(taskData, taskId, npcId, textIndex, eventId);
        } else {
            for (BaseFishPondCondition baseFishPondCondition : taskConditionMap.values()) {
                FishPondTaskData taskData = baseFishPondCondition.getFishPondTaskData();
                if (taskData.isGetReward()) {
                    taskData.setGetReward(false);
                    extendParam = createTaskCondition(taskData, taskId, npcId, textIndex, eventId);
                    break;
                }
            }
        }

        //日志
        AutoLogMgr.add(new LogFishPondTask(player.getUserId(), taskId, false, ""));
        return extendParam;
    }

    public String createTaskCondition(FishPondTaskData taskData, int taskId, int npcId, int textIndex, int eventId) {
        taskData.setTaskId(taskId);
        taskData.setNpcId(npcId);
        taskData.setValue(BigInteger.ZERO);
        taskData.setEventId(eventId);
        taskData.setTextIndex(textIndex);

        BaseFishPondCondition condition = BaseFishPondCondition.createCondition(player, taskData);
        if (condition != null) {
            condition.initFishPondTaskAction();
            taskConditionMap.put(condition.getFishPondTaskData().getId(), condition);
            return condition.getFishPondTaskData().getExtendParam();
        }
        return "";
    }

    /**
     * 领取委托任务奖励
     * @param id 任务自增id
     * @return ret
     */
    public int getTaskReward(long id) {
        BaseFishPondCondition baseFishPondCondition = taskConditionMap.get(id);
        if (baseFishPondCondition == null) {
            return GameErrorCode.E_TASK_NO_FOUND;
        }
        int ret = baseFishPondCondition.finish(player);
        if (ret == 0) {
            syncTaskData();
            FishPondEventInfo eventInfo = FishPondMgr.getFishPondEventInfo(baseFishPondCondition.getFishPondTaskData().getEventId());
            assert eventInfo != null;
            if (!isHundredFishing) {
                FishPondProto.GetTaskRewardRespMsg.Builder respMsg = FishPondProto.GetTaskRewardRespMsg.newBuilder();
                respMsg.setReward(eventInfo.getReward());
                respMsg.setRet(0);
                player.sendPacket(ClientProtocol.U_FISH_POND_GET_TASK_REWARD, respMsg);
            }

            //日志
            AutoLogMgr.add(new LogFishPondTask(player.getUserId(), baseFishPondCondition.getFishPondTaskData().getTaskId(), true, eventInfo.getReward()));
        }
        return ret;
    }

    /**
     * 首次查看图鉴
     * @param type 类型 1：鱼 else 奇物
     * @param id id
     * @return ret
     */
    public int readSampleFirst(int type, int id) {
        if (type == eFishPondItemType.Fish.getValue()) {
            FishData fishData = fishDataMap.get(id);
            if (fishData == null) {
                return GameErrorCode.E_FISH_POND_SAMPLE_IS_LOCK;
            }
            fishData.setReadSample(true);
            syncSingleFish(fishData);
        } else {
            FishPondSpecialItemData fishPondSpecialItemData = fishPondSpecialItemDataMap.get(id);
            if (fishPondSpecialItemData == null) {
                return GameErrorCode.E_FISH_POND_SAMPLE_IS_LOCK;
            }
            fishPondSpecialItemData.setReadSample(true);
            syncSingleSpecialItem(fishPondSpecialItemData);
        }
        return 0;
    }

    /**
     * 领取图鉴解锁奖励
     * @param type 类型 1：鱼 else 奇物
     * @param id id
     * @param idList
     * @return ret
     */
    public int getFishPondItemUnLockReward(int type, int id, List<Integer> idList) {
        if(idList.size() == 0){
            idList.add(id);
        }
        Property totalReward = new Property();
        List<FishData> changeFishList = new ArrayList<>();
        List<FishPondSpecialItemData> changeItemList = new ArrayList<>();
        FishPondProto.GetItemUnLockRewardRespMsg.Builder respMsg = FishPondProto.GetItemUnLockRewardRespMsg.newBuilder();
        respMsg.setRet(0);

        for (Integer fishId : idList) {
            FishData fishData = fishDataMap.get(fishId);
            if (fishData == null) {
                continue;
            }
            if (fishData.isGetUnLockReward()) {
                continue;
            }
            FishPondItemConfig fishPondItemConfig = FishPondMgr.getFishPondItemConfig(fishId);
            int quality = fishPondItemConfig.getQuality();
            String reward = fishPondItemConfig.getRewardList();
            fishData.setGetUnLockReward(true);
            AutoLogMgr.add(new LogFishPondSampleReward(player.getUserId(), type, fishId, quality, reward));
            player.getModule(CurrencyModule.class).addCurrency(fishPondItemConfig.getRewardList(), eLogMoneyType.Manor, eLogMoneyType.ManorFishPondGetItemUnLockReward);
            totalReward.addProperty(PropertyHelper.parseStringToProperty(reward));
            changeFishList.add(fishData);
        }

        for (Integer specialId : idList) {
            FishPondSpecialItemData fishPondSpecialItemData = fishPondSpecialItemDataMap.get(specialId);
            if (fishPondSpecialItemData == null) {
                continue;
            }
            if (fishPondSpecialItemData.isGetUnLockReward()) {
                continue;
            }
            fishPondSpecialItemData.setGetUnLockReward(true);
            GoodsInfo goodsInfo = GoodsMgr.getGoodsById(specialId);
            int quality = goodsInfo.getQuality();
            String reward = goodsInfo.getExtendParam().split("\\|")[1];
            AutoLogMgr.add(new LogFishPondSampleReward(player.getUserId(), type, specialId, quality, reward));
            player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.Manor, eLogMoneyType.ManorFishPondGetItemUnLockReward);

            totalReward.addProperty(PropertyHelper.parseStringToProperty(reward));
            changeItemList.add(fishPondSpecialItemData);
        }

        if(!changeItemList.isEmpty()){
            syncSpecialItem(changeItemList);
        }
        if(!changeFishList.isEmpty()){
            syncFishData(changeFishList);
        }

        respMsg.setReward(PropertyHelper.parsePropertyToString(totalReward));
        respMsg.setRet(0);
        player.sendPacket(ClientProtocol.U_FISH_POND_GET_ITEM_UNLOCK_REWARD, respMsg);
        return 0;
    }

    /**
     * 装备鱼类
     *
     * @param fishId    鱼类id
     * @param patronsId 门客id
     * @return ret
     */
    public int equipFish(int fishId, int patronsId) {
        //卸下鱼
        if (fishId == 0) {
            disEquipFish(patronsId);
            return 0;
        }
        //装备鱼
        FishData fishData = fishDataMap.get(fishId);
        if (fishData == null) {
            return GameErrorCode.E_FISH_POND_FISH_IS_LOCK;
        }
        FishPondItemConfig fishPondItemConfig = FishPondMgr.getFishPondItemConfig(fishId);
        if (fishPondItemConfig == null) {
            return GameErrorCode.E_FISH_POND_FISH_CONFIG_NO_FOUND;
        }
        if (GameConfig.FISHPOND_EQUIP_FISH_QUALITY_LIMIT > fishPondItemConfig.getQuality()) {
            return GameErrorCode.E_FISH_POND_FISH_CANT_EQUIP;
        }
        UserPatrons userPatrons = player.getModule(PatronsModule.class).getUserPatrons(patronsId);
        if (userPatrons == null) {
            return GameErrorCode.E_PATRONS_NO_FOUND;
        }
        //门客装备精进等级要求
        if (userPatrons.getStageLv() < GameConfig.FISHPOND_EQUIP_FISH_PATRONS_STAGE_LIMIT) {
            return GameErrorCode.E_PATRONS_STAGE_LEVEL_NO_ENOUGH;
        }
        if (!canMountFish(fishId, patronsId)) {
            return GameErrorCode.E_PATRONS_CAN_NOT_MOUNT_FISH_IN_ACTIVITY;
        }
        //是否允许装备
        if(!UnionPhaseWarMgr.canMountFish(player, fishId, patronsId)){
            return GameErrorCode.E_UNION_WAR_ACTIVITY_FISH_IN_WAR_NOT_MOUNT;
        }
        //超过免费次数 需要消耗
        String cost = "";
        if (fishData.getEquipTimes() >= GameConfig.FISHPOND_DEFAULT_EQUIP_TIMES) {
            //装备消耗
            int ingots = FishPondMgr.getFishEquipCost(fishData.getEquipBuyTimes());
            Property costProperty = new Property(GameConfig.GAME_MONEY_INGOTS, BigInteger.valueOf(ingots));
            if (!player.getModule(CurrencyModule.class).removeCurrency(costProperty,
                    eLogMoneyType.Manor, eLogMoneyType.ManorFishPondFishEquip)) {
                return GameErrorCode.E_BAG_INGOTS_NO_ENOUGH;
            }
            fishData.setEquipBuyTimes(fishData.getEquipBuyTimes() + 1);
            cost = PropertyHelper.parsePropertyToString(costProperty);
        }
        //如果门客装备了鱼,先把装备的卸下
        disEquipFish(patronsId);
        //如果鱼被装备了,先卸下来
        disEquipFish(fishData.getEquipPatronsId());
        fishData.setEquipPatronsId(patronsId);
        fishData.setEquipTimes(fishData.getEquipTimes() + 1);
        syncSingleFish(fishData);
        syncPatrons(fishData.getEquipPatronsId());

        AutoLogMgr.add(new LogFishEquip(
                player.getUserId(),
                patronsId,
                fishId,
                true,
                cost
        ));

        //商会战活动
        UnionPhaseWarMgr.equipFish(player, fishId, patronsId);
        player.getModule(RankUnionWarModule.class).equipVehicleOrFish(patronsId);
        return 0;
    }

    /**
     * 卸下鱼
     * @param patronsId 门客id
     */
    private void disEquipFish(int patronsId) {
        if (patronsId == 0) {
            return;
        }
        FishData userFishByPatrons = FishPondMgr.getUserFishByPatrons(patronsId, fishDataMap);
        if (userFishByPatrons != null) {
            userFishByPatrons.setEquipPatronsId(0);
            syncSingleFish(userFishByPatrons);
            syncPatrons(patronsId);

            //商会战活动
            UnionPhaseWarMgr.dismountFish(player, patronsId, userFishByPatrons.getFishId());
        }

        AutoLogMgr.add(new LogFishEquip(
                player.getUserId(),
                patronsId,
                0,
                false,
                ""
        ));
    }

    /**
     * 增加鱼塘积分
     * @param value 增加值
     */
    private void addFishPondScore(long value) {
        fishPondData.setFishPondScore(fishPondData.getFishPondScore() + value);
        RankMgr.changeUserRank(eBigRankType.Normal.getValue(), player.getUserId(), BigInteger.valueOf(fishPondData.getFishPondScore()), eRankType.FishPondScore.getValue(), "" + fishPondData.getFishPondLv());
        player.notifyListener(eGamePlayerEventType.FishPondRankActivityRank.getValue(), value);
        player.notifyListener(eGamePlayerEventType.FishPondScoreAdd.getValue(), value);
    }

    /**
     * 鱼类徽章升级
     * @return ret
     */
    public int fishPondUpgrade() {
        int oldFishPondBadgeId = fishPondData.getFishPondLv();
        FishPondBadgeConfig nextFishPondBadgeConfig = FishPondMgr.getNextFishPondBadgeConfig(fishPondData.getFishPondLv());
        if (nextFishPondBadgeConfig == null) {
            return GameErrorCode.E_FISH_POND_BADGE_LV_IS_LIMIT;
        }
        FishPondBadgeConfig fishPondBadgeConfig = FishPondMgr.getFishPondBadgeConfigMap().get(fishPondData.getFishPondLv());
        if (fishPondBadgeConfig.getNeedFisherPoints() > fishPondData.getFishPondScore()) {
            return GameErrorCode.E_FISH_POND_FISHER_POINT_IS_NO_ENOUGH;
        }
        fishPondData.setFishPondLv(nextFishPondBadgeConfig.getId());
        //同步商铺赚速
        player.getModule(EarnSpeedModule.class).scheduleAddSilver();
        // 更新徽章
        updateBadge();

        FishPondProto.FishPondLvUpgradeRespMsg.Builder respMsg = FishPondProto.FishPondLvUpgradeRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setFishPondLv(fishPondData.getFishPondLv());
        player.sendPacket(ClientProtocol.U_FISH_POND_LV_UPGRADE, respMsg);
        RankMgr.changeUserRank(eBigRankType.Normal.getValue(), player.getUserId(), BigInteger.valueOf(fishPondData.getFishPondScore()), eRankType.FishPondScore.getValue(), "" + fishPondData.getFishPondLv());

        //日志
        AutoLogMgr.add(new LogFishPondBadge(player.getUserId(), fishPondData.getFishPondLv(), oldFishPondBadgeId, fishPondData.getFishPondScore()));
        return 0;
    }

    /**
     * 设置展示鱼群
     * @param fishIdList 鱼类id list
     */
    public int setShowFish(List<Integer> fishIdList) {
        for (FishData fishData : fishDataMap.values()) {
            fishData.setShow(fishIdList.contains(fishData.getFishId()));
        }
        syncFishData(new ArrayList<>(fishDataMap.values()));
        return 0;
    }

    /**
     * 喂鱼
     *
     * @param feedFishId  被喂的鱼id
     * @param fishSkillId 要提升的技能id
     * @param fedFishList 用来喂的鱼id list
     * @param exp         经验
     * @return ret
     */
    public int feedFish(int feedFishId, int fishSkillId, List<FedFish> fedFishList, long exp) {
        FishPondItemConfig config = FishPondMgr.getFishPondItemConfig(feedFishId);
        if (config == null) {
            return GameErrorCode.E_FISH_POND_FISH_CONFIG_NO_FOUND;
        }
        int quality = config.getQuality();
        FishData fishData = fishDataMap.get(feedFishId);
        if (fishData == null) {
            return GameErrorCode.E_FISH_POND_FISH_IS_LOCK;
        }
        FishSkillData fishSkillData = fishData.getFishSkillDataMap().get(fishSkillId);
        if (fishSkillData == null) {
            return GameErrorCode.E_FISH_POND_FISH_SKILL_IS_LOCK;
        }
        int oldSkillLv = fishSkillData.getLv();
        SkillInfo skillInfo = SkillMgr.getSkillInfo(fishSkillData.getFishSkillId());
        if (skillInfo == null) {
            return GameErrorCode.E_FISH_POND_FISH_SKILL_CONFIG_NO_FOUND;
        }
        if (skillInfo.getMaxLevel() <= fishSkillData.getLv()) {
            return GameErrorCode.E_FISH_POND_FISH_SKILL_LEVEL_MAX;
        }
        if (!checkFishIsEnough(fedFishList)) {
            return GameErrorCode.E_FISH_POND_FISH_NUM_NO_ENOUGH;
        }
        //检测是不是拿了没满级的珍惜鱼
        int checkNoMaxPreciousLevel = checkNoMaxPreciousLevel(fedFishList);
        if (checkNoMaxPreciousLevel != 0){
            return checkNoMaxPreciousLevel;
        }
        if (fishPondData.getExp() < exp) {
            return GameErrorCode.E_FISH_POND_EXP_NO_ENOUGH;
        }
        long addExp = removeFedFishListAndCalcExp(fedFishList, exp);
        fishSkillData.setCurExp(fishSkillData.getCurExp() + addExp);
        addExp = 0L;
        boolean lvUp = false;
        while (fishSkillData.getCurExp() > 0 && skillInfo.getMaxLevel() > fishSkillData.getLv()) {
            SkillUpgradeInfo skillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), fishSkillData.getLv());
            if (skillUpgradeInfo == null) {
                break;
            }
            if (fishSkillData.getCurExp() >= skillUpgradeInfo.getConsumeCount()) {
                fishSkillData.setCurExp(fishSkillData.getCurExp() - skillUpgradeInfo.getConsumeCount());
                fishSkillData.setLv(fishSkillData.getLv() + 1);
                lvUp = true;

            } else {
                break;
            }
        }
        if (fishSkillData.getLv() >= skillInfo.getMaxLevel()) {
            addExp = fishSkillData.getCurExp();
            fishSkillData.setCurExp(0);
        }
        //剩余经验回收
        fishPondData.setExp(fishPondData.getExp() + addExp);
        syncFishData(new ArrayList<>(fishDataMap.values()));

        if (lvUp) {
            syncPatrons(fishData.getEquipPatronsId());
        }

        FishPondProto.FeedFishRespMsg.Builder respMsg = FishPondProto.FeedFishRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setRecycleExp(addExp);
        respMsg.setCurExp(fishPondData.getExp());
        player.sendPacket(ClientProtocol.U_FISH_POND_FEED_FISH, respMsg);

        //日志
        AutoLogMgr.add(new LogFishPondFishFeed(player.getUserId(), feedFishId, quality, fishSkillId, fishSkillData.getLv(), oldSkillLv, JSON.toJSONString(fedFishList), exp, addExp));
        return 0;
    }


    /**
     * 检查鱼是否足够
     * @param fedFishList 用来喂的鱼id list
     * @return bool
     */
    private boolean checkFishIsEnough(List<FedFish> fedFishList) {
        for (FedFish fedFish : fedFishList) {
            FishData fishData = fishDataMap.get(fedFish.getFedFishId());
            if (fishData == null || fishData.getNum() < fedFish.getCount()) {
                return false;
            }
        }
        return true;
    }

    /**
     * 检查是否进了没满级的珍惜鱼
     */
    private int checkNoMaxPreciousLevel(List<FedFish> fedFishList){

        for (FedFish fedFish : fedFishList) {
            FishData fishData = fishDataMap.get(fedFish.getFedFishId());
            FishPondItemConfig fishPondItemConfig = FishPondMgr.getFishPondItemConfig(fishData.getFishId());
            int quality = fishPondItemConfig.getQuality();
            if(quality >= 5){       //无双不给喂
                return GameErrorCode.E_FISH_POND_WU_SHUANG_FISH_CAN_NOT_FEEDS;
            }
            //只有珍惜鱼需要检测
            if(quality >= GameConfig.FISHPOND_FISH_RARITY_QUALITY_LIMIT){
                int upgradeSkillId = FishPondMgr.getFishUpgradeSkillConfig(fedFish.getFedFishId());
                if (upgradeSkillId == 0) {
                    return GameErrorCode.E_FISH_POND_FISH_UPGRADE_SKILL_CONFIG_NO_FOUND;
                }
                //先拿技能
                SkillInfo skillInfo = SkillMgr.getSkillInfo(upgradeSkillId);
                if (skillInfo == null) {
                    return GameErrorCode.E_FISH_POND_FISH_UPGRADE_SKILL_CONFIG_NO_FOUND;
                }
                //如果没有满级 不给用这条鱼
                if (skillInfo.getMaxLevel() > fishData.getLv()) {
                    return GameErrorCode.E_FISH_POND_FEED_RARITY_FISH_NO_MAX;
                }

            }
        }
        return 0;
    }


    /**
     * 移除用来喂的鱼
     * @param fedFishList 用来喂的鱼 id list
     * @param exp 经验
     * @return exp
     */
    private long removeFedFishListAndCalcExp(List<FedFish> fedFishList, long exp) {
        long addExp = 0L;
        for (FedFish fedFish : fedFishList) {
            FishData fishData = fishDataMap.get(fedFish.getFedFishId());
            fishData.setNum(fishData.getNum() - fedFish.getCount());
            FishPondItemConfig fishPondItemConfig = FishPondMgr.getFishPondItemConfig(fedFish.getFedFishId());
            addExp += fishPondItemConfig.getExp() * fedFish.getCount();
        }
        fishPondData.setExp(fishPondData.getExp() - exp);
        addExp += exp;
        return addExp;
    }

    /**
     * 鱼类晋升
     * @param fishId 晋升的鱼id
     * @return ret
     */
    public int fishUpgrade(int fishId) {
        FishPondItemConfig config = FishPondMgr.getFishPondItemConfig(fishId);
        if (config == null) {
            return GameErrorCode.E_FISH_POND_FISH_CONFIG_NO_FOUND;
        }
        FishData fishData = fishDataMap.get(fishId);
        if (fishData == null) {
            return GameErrorCode.E_FISH_POND_FISH_IS_LOCK;
        }
        int oldLv = fishData.getLv();
        int upgradeSkillId = FishPondMgr.getFishUpgradeSkillConfig(fishId);
        if (upgradeSkillId == 0) {
            return GameErrorCode.E_FISH_POND_FISH_UPGRADE_SKILL_CONFIG_NO_FOUND;
        }
        SkillInfo skillInfo = SkillMgr.getSkillInfo(upgradeSkillId);
        if (skillInfo == null) {
            return GameErrorCode.E_FISH_POND_FISH_UPGRADE_SKILL_CONFIG_NO_FOUND;
        }
        if (skillInfo.getMaxLevel() <= fishData.getLv()) {
            return GameErrorCode.E_FISH_POND_FISH_UPGRADE_LV_MAX;
        }
        SkillUpgradeInfo skillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), fishData.getLv());
        if (skillUpgradeInfo == null) {
            return GameErrorCode.E_FISH_POND_FISH_UPGRADE_SKILL_CONFIG_NO_FOUND;
        }
        long consumeCount = skillUpgradeInfo.getConsumeCount();
        if (!checkFishEnoughAndRemove(fishId, consumeCount)) {
            return GameErrorCode.E_FISH_POND_FISH_NUM_NO_ENOUGH;
        }
        fishData.setLv(fishData.getLv() + 1);
        notifyFishSkillUnLock(fishData);
        syncSingleFish(fishData);
        syncPatrons(fishData.getEquipPatronsId());

        //日志
        AutoLogMgr.add(new LogFishPondFishUpgrade(player.getUserId(), fishId, config.getQuality(), fishData.getLv(), oldLv, consumeCount));
        return 0;
    }

    private void syncPatrons(int patronsId) {
        //同步门客
        PatronsModule module = player.getModule(PatronsModule.class);
        UserPatrons userPatrons = module.getUserPatrons(patronsId);
        if (userPatrons != null) {
            module.onPatronsChange(userPatrons);
        }
    }

    /**
     * 通知鱼类技能解锁
     * @param fishData 鱼类数据
     */
    private void notifyFishSkillUnLock(FishData fishData) {
        FishPondItemConfig fishPondItemConfig = FishPondMgr.getFishPondItemConfig(fishData.getFishId());
        String[] skillConfigArr = fishPondItemConfig.getSkills().split("\\|");
        boolean unlock = false;
        for (int i = 1; i < skillConfigArr.length; i++) {
            String skillConfigStr = skillConfigArr[i];
            String[] skillConfigSplit = skillConfigStr.split(",");
            if (Integer.parseInt(skillConfigSplit[1]) <= fishData.getLv()) {
                initFishSkill(fishData, Integer.parseInt(skillConfigSplit[0]));
                unlock = true;
            }
        }
        if (unlock) {
            syncPatrons(fishData.getEquipPatronsId());
        }
    }

    /**
     * 初始化鱼的技能
     * @param fishData 鱼类数据
     * @param fishSkillId 技能id
     */
    private void initFishSkill(FishData fishData, int fishSkillId) {
        if (fishData.getFishSkillDataMap().containsKey(fishSkillId)) {
            return;
        }
        FishSkillData skillData = new FishSkillData();
        skillData.setUserId(player.getUserId());
        skillData.setFishId(fishData.getFishId());
        skillData.setFishSkillId(fishSkillId);
        skillData.setLv(1);
        skillData.setCurExp(0);
        skillData.setInsertOption();
        fishData.getFishSkillDataMap().put(fishSkillId, skillData);
    }

    /**
     * 检测鱼类是否足够并且移除
     * @param fishId 鱼类id
     * @param consumeCount 消耗数量
     * @return bool
     */
    private boolean checkFishEnoughAndRemove(int fishId, long consumeCount) {
        FishData fishData = fishDataMap.get(fishId);
        if (fishData.getNum() < consumeCount) {
            return false;
        }
        fishData.setNum(fishData.getNum() - consumeCount);
        return true;
    }

    /**
     * 鱼类回收
     * @param fishId 鱼类id
     * @return
     */
    public int recycleFish(int fishId) {
        FishPondItemConfig config = FishPondMgr.getFishPondItemConfig(fishId);
        if (config == null) {
            return GameErrorCode.E_FISH_POND_FISH_CONFIG_NO_FOUND;
        }
        long nowTime = System.currentTimeMillis();
        if (nowTime - fishPondData.getLastRecycleTime() < GameConfig.FISHPOND_EQUIP_FISH_RECOVER_TIME * DateHelper.HOUR_MILLIONS) {
            return GameErrorCode.E_FISH_POND_FISH_RECYCLE_CD;
        }
        FishData fishData = fishDataMap.get(fishId);
        if (fishData == null) {
            return GameErrorCode.E_FISH_POND_FISH_IS_LOCK;
        }
        long recycleExp = 0;
        for (FishSkillData skillData : fishData.getFishSkillDataMap().values()) {
            recycleExp += FishPondMgr.calcCostExp(skillData);
        }
        if (recycleExp <= 0) {
            return GameErrorCode.E_FISH_POND_NO_EXP_RECYCLE;
        }
        String skillListStr = JSON.toJSONString(fishData.getFishSkillDataMap());
        for (FishSkillData skillData : fishData.getFishSkillDataMap().values()) {
            skillData.setCurExp(0);
            skillData.setLv(1);
        }
        fishPondData.setExp(fishPondData.getExp() + recycleExp);
        fishPondData.setLastRecycleTime(nowTime);
        syncSingleFish(fishData);
        syncPatrons(fishData.getEquipPatronsId());
        FishPondProto.RecycleFishRespMsg.Builder respMsg = FishPondProto.RecycleFishRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setRecycleExp(recycleExp);
        respMsg.setLastRecycleTime(nowTime);
        respMsg.setCurExp(fishPondData.getExp());
        player.sendPacket(ClientProtocol.U_FISH_POND_RECYCLE_FISH, respMsg);

        //日志
        AutoLogMgr.add(new LogFishPondFishRecycle(player.getUserId(), fishId, config.getQuality(), skillListStr, recycleExp));
        return 0;
    }

    /**
     * 每日重置
     */
    public void resetOneDay() {
        long zeroTime = LocalDateTimeHelper.getZeroTimeTimeStamp() / 1000;
        if (null != fishDataMap) {
            List<FishData> syncList = new ArrayList<>();
            for (FishData fishData : fishDataMap.values()) {
                if (fishData.getLastUpdateTime() < zeroTime) {
                    // 不等于0才同步
                    if (fishData.getEquipTimes() != 0 || fishData.getEquipBuyTimes() != 0) {
                        syncList.add(fishData);
                    }
                    fishData.setEquipTimes(0);
                    fishData.setEquipBuyTimes(0);
                    fishData.setLastUpdateTime(zeroTime);
                }
            }
            syncFishData(syncList);
        }
    }

    public void addPatronsBindData(int activityId, int patronsId, int fishId) {
        PatronsFishBindingData data = patronsFishBindingDataMap.get(fishId);
        if (data == null) {
            data = new PatronsFishBindingData();
            data.setFishId(fishId);
            data.setInsertOption();
            data.setUserId(player.getUserId());
            patronsFishBindingDataMap.put(fishId, data);
        }
        data.setPatronsId(patronsId);
        data.addActivityId(activityId);
        data.setLastUpdateTime(System.currentTimeMillis());
        syncPatronsBindMsg(Collections.singletonList(data));
    }

    public void addPatronsBindSystem(int systemId, int patronsId, int fishId, long endTime) {
        PatronsFishBindingData data = patronsFishBindingDataMap.get(fishId);
        if (data == null) {
            data = new PatronsFishBindingData();
            data.setFishId(fishId);
            data.setInsertOption();
            data.setUserId(player.getUserId());
            patronsFishBindingDataMap.put(fishId, data);
        }
        data.setPatronsId(patronsId);
        data.addSystem(systemId, endTime);
        data.setLastUpdateTime(System.currentTimeMillis());
        syncPatronsBindMsg(Collections.singletonList(data));
    }

    public void syncPatronsBindMsg(Collection<PatronsFishBindingData> dataList) {
        if (!dataList.isEmpty()) {
            FishPondProto.SyncPartonsFishBindingMsg.Builder syncMsg = FishPondProto.SyncPartonsFishBindingMsg.newBuilder();
            for (PatronsFishBindingData data : dataList) {
                FishPondProto.PartonsFishBindingMsg.Builder msg = FishPondProto.PartonsFishBindingMsg.newBuilder();
                msg.setPatronsId(data.getPatronsId());
                msg.setFishId(data.getFishId());
                msg.setActivityId(0);
                if (data.getActivityIdList().size() > 0) {
                    msg.setActivityId(data.getActivityIdList().get(0));
                }
                if (data.getSystemId() > 0) {
                    msg.setSystemId(data.getSystemId());
                    msg.setSystemEndTime(data.getSystemEndTime());
                }

                syncMsg.addData(msg);
            }
            player.sendPacket(ClientProtocol.U_FISH_POND_ACTIVITY_PATRONS_BIND, syncMsg);
        }
    }

    public void checkAndReset() {
        int hours = DateHelper.getHours();
        long now = System.currentTimeMillis() / 1000;
        long needResetTime = DateHelper.getDateByHours(22).getTime() / 1000;
        boolean needSync = false;
        for (PatronsFishBindingData data : new ArrayList<>(patronsFishBindingDataMap.values())) {
            long lastResetTime = data.getLastUpdateTime() / 1000;
            if (DateHelper.isSameDay(now, lastResetTime)) {
                //如果是同一天 只有过了22点才行
                if (hours < 22) {
                    continue;
                }
                if (lastResetTime >= needResetTime) {
                    continue;
                }
            }
            if (now < data.getSystemEndTime()) {
                continue;
            }
            data.setLastUpdateTime(now * 1000);
            data.setPatronsId(0);
            data.getActivityIdList().clear();
            needSync = true;
        }
        if (needSync) {
            syncPatronsBindMsg(new ArrayList<>(patronsFishBindingDataMap.values()));
        }
    }

    public void checkVehicleBindingActivity() {
        List<PatronsFishBindingData> syncList = new ArrayList<>();
        for (PatronsFishBindingData data : new ArrayList<>(patronsFishBindingDataMap.values())) {
            boolean needSync = false;
            List<Integer> activityIdList = data.getActivityIdList();
            if (activityIdList != null) {
                for (Integer activityId : activityIdList) {
                    ActivityInfo activityInfo = NormalActivityMgr.getActivityInfo(activityId);
                    if (activityInfo == null) {
                        activityInfo = StrongholdActivityMgr.getInTimeActivityInfo(activityId);
                    }
                    if (activityInfo == null) {
                        data.removeActivityId(activityId);
                        needSync = true;
                        break;
                    }
                }
            }
            if (needSync) {
                syncList.add(data);
            }
        }
        syncPatronsBindMsg(syncList);
    }

    private boolean canMountFish(int fishId, int patronsId) {
        PatronsFishBindingData bindingData = patronsFishBindingDataMap.get(fishId);
        if (bindingData == null) {
            return true;
        }
        if(bindingData.getPatronsId() == patronsId || bindingData.getPatronsId() == 0){
            return true;
        }

        if (DateHelper.getCurrentSecond() >= bindingData.getSystemEndTime()) {
            bindingData.setPatronsId(0);
            return true;
        }

        return false;
    }

    /**
     * 累计钓起珍稀鱼数目
     * @return
     */
    public long calcRarityFishAccCount() {
        long count = 0;
        for (FishData fishData : fishDataMap.values()) {
            FishPondItemConfig fishConfig = FishPondMgr.getFishPondItemConfig(fishData.getFishId());
            if (fishConfig.getQuality() >= GameConfig.FISHPOND_FISH_RARITY_QUALITY_LIMIT) {
                count += fishData.getAccFishingCount();
            }
        }
        return count;
    }


    /**
     * 道具途径获得鱼食
     * @param goodsId
     * @param longValue
     * @param son
     */
    public void addExp(int goodsId, long longValue, eLogMoneyType son) {
        fishPondData.setExp(fishPondData.getExp() + longValue);
        syncFishPondData();
        //日志
        AutoLogMgr.add(new LogFishPondItem(player.getUserId(), goodsId, true, longValue, fishPondData.getExp(), 0, son.getValue()));
    }

    public void save() {
        if (fishPondData != null) {
            if (fishPondData.isInsertOption()) {
                UserFishPondBusiness.addFishPondData(fishPondData);
            } else if (fishPondData.isUpdateOption()) {
                UserFishPondBusiness.updateFishPondData(fishPondData);
            }
        }

        for (FishData fishData : fishDataMap.values()) {
            if (fishData.isInsertOption()) {
                UserFishPondBusiness.addFishData(fishData);
            } else if (fishData.isUpdateOption()) {
                UserFishPondBusiness.updateFishData(fishData);
            }

            for (FishSkillData fishSkillData : fishData.getFishSkillDataMap().values()) {
                if (fishSkillData.isInsertOption()) {
                    UserFishPondBusiness.addFishSkillData(fishSkillData);
                } else if (fishSkillData.isUpdateOption()) {
                    UserFishPondBusiness.updateFishSkillData(fishSkillData);
                }
            }
        }

        for (FishPondSpecialItemData specialItemData : fishPondSpecialItemDataMap.values()) {
            if (specialItemData.isInsertOption()) {
                UserFishPondBusiness.addSpecialItemData(specialItemData);
            } else if (specialItemData.isUpdateOption()) {
                UserFishPondBusiness.updateSpecialItemData(specialItemData);
            }
        }

        for (BaseFishPondCondition baseFishPondCondition : taskConditionMap.values()) {
            FishPondTaskData taskData = baseFishPondCondition.getFishPondTaskData();
            if (taskData.isInsertOption()) {
                UserFishPondBusiness.addFishPondTaskData(taskData);
            } else if (taskData.isUpdateOption()) {
                UserFishPondBusiness.updateFishPondTaskData(taskData);
            }
        }

        if (patronsFishBindingDataMap != null) {
            for (PatronsFishBindingData data : new ArrayList<>(patronsFishBindingDataMap.values())) {
                if (data.isInsertOption()) {
                    UserFishPondBusiness.addPatronsFishBinding(data);
                } else if (data.isUpdateOption()) {
                    UserFishPondBusiness.updatePatronsFishBinding(data);
                }
            }
        }
    }

    public void commitFishAdd() {
        List<FishPondProto.FishCurrencyTemp.Builder> list;
        synchronized (fishCurrencyAddSyncList) {
            list = new ArrayList<>(fishCurrencyAddSyncList);
            fishCurrencyAddSyncList.clear();
        }
        if (list.isEmpty()) {
            return;
        }
        FishPondProto.FishCurrencyAddSyncMsg.Builder syncMsg = FishPondProto.FishCurrencyAddSyncMsg.newBuilder();
        for (FishPondProto.FishCurrencyTemp.Builder temp : list) {
            syncMsg.addFish(temp);
        }
        player.sendPacket(ClientProtocol.U_FISH_ADD_CURRENCY_SYNC, syncMsg);
    }

    /**
     * 更新勋章
     */
    public void updateBadge(){
        if (SystemOpenMgr.systemOpen(player, eSystemId.BadgeShow.getValue())) {
            if (fishPondData == null) {
                return;
            }
            int fishPondBadgeId = fishPondData.getFishPondLv();
            if (fishPondBadgeId == 0) {
                return;
            }
            player.getModule(BadgeModule.class).addBadge(fishPondData.getFishPondLv(), eBadgeType.FishPond.getValue());
        }
    }

    public int changeAutoFinishTask() {
        fishPondData.setAutoFinishTask(!fishPondData.isAutoFinishTask());
        syncFishPondData();
        return 0;
    }
}
